package cc.leap.service;

import cc.leap.constant.UserConstants;
import cc.leap.mapper.SysUserMapper;
import cc.leap.mapper.SysUserPostMapper;
import cc.leap.mapper.SysUserRoleMapper;
import cc.leap.model.PageQuery;
import cc.leap.model.TableDataInfo;
import cc.leap.model.domain.SysUser;
import cc.leap.model.domain.SysUserPost;
import cc.leap.model.domain.SysUserRole;
import cc.leap.utils.StringUtils;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Tran;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static cc.leap.model.domain.table.SysDeptTableDef.SYS_DEPT;
import static cc.leap.model.domain.table.SysRoleTableDef.SYS_ROLE;
import static cc.leap.model.domain.table.SysUserRoleTableDef.SYS_USER_ROLE;
import static cc.leap.model.domain.table.SysUserTableDef.SYS_USER;

/**
 * SysUserService
 *
 * @author leap
 * @date 2024/8/15
 */
@Component
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {
    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    @Inject
    SysUserMapper sysUserMapper;

    @Inject
    SysUserRoleMapper userRoleMapper;

    @Inject
    SysUserPostMapper userPostMapper;

    private QueryWrapper buildListQueryWrapper(SysUser userBo) {
        QueryWrapper queryWrapper = QueryWrapper.create();
        queryWrapper.select(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.NICK_NAME, SYS_USER.USER_NAME, SYS_USER.EMAIL, SYS_USER.AVATAR, SYS_USER.PHONENUMBER, SYS_USER.SEX, SYS_USER.STATUS, SYS_USER.DEL_FLAG, SYS_USER.LOGIN_IP, SYS_USER.LOGIN_DATE, SYS_USER.CREATE_BY, SYS_USER.CREATE_TIME, SYS_USER.REMARK, SYS_DEPT.DEPT_NAME, SYS_DEPT.LEADER)
                .from(SYS_USER).as("u")
                .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
                .where(SYS_USER.DEL_FLAG.eq(0));
        if (StringUtils.isNotEmpty(userBo.getUserName())) {
            queryWrapper.like("user_name", userBo.getUserName());
        }
        if (StringUtils.isNotEmpty(userBo.getStatus())) {
            queryWrapper.eq("status",userBo.getStatus());
        }
        if (StringUtils.isNotEmpty(userBo.getPhonenumber())) {
            queryWrapper.like("phonenumber",userBo.getPhonenumber());
        }
        Map<String, Object> params = userBo.getParams();
        if (params.get("beginTime") != null && params.get("endTime") != null) {
            queryWrapper.between("create_time", params.get("beginTime"), params.get("endTime"));
        }

        return queryWrapper;
    }

    public TableDataInfo<SysUser> selectUserPage(SysUser user) {
        QueryWrapper queryWrapper = buildListQueryWrapper(user);
        Page<SysUser> page = this.pageAs(PageQuery.build(), queryWrapper, SysUser.class);
        return TableDataInfo.build(page);
    }

    public SysUser selectUserById(Long userId) {
        return sysUserMapper.selectUserById(userId);
    }

    public SysUser selectUserByUserName(String userName) {
        return sysUserMapper.selectByUsername(userName);
    }

    public boolean checkUserNameUnique(SysUser user) {

        SysUser info = sysUserMapper.checkUserNameUnique(user.getUserName());
        if (ObjectUtil.isNotNull(info) && info.getUserId().longValue() != user.getUserId().longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    public boolean checkPhoneUnique(SysUser user) {
        SysUser info = sysUserMapper.checkPhoneUnique(user.getPhonenumber());
        if (ObjectUtil.isNotNull(info) && info.getUserId().longValue() != user.getUserId().longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    public boolean checkEmailUnique(SysUser user) {
        SysUser info = sysUserMapper.checkEmailUnique(user.getEmail());
        if (ObjectUtil.isNotNull(info) && info.getUserId().longValue() != user.getUserId().longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Tran
    public int insertUser(SysUser user) {
        int rows = sysUserMapper.insertUser(user);
        insertUserPost(user);
        insertUserRole(user.getUserId(), user.getRoleIds());
        return rows;
    }

    public void insertUserPost(SysUser user) {
        Long[] posts = user.getPostIds();
        if (ArrayUtil.isNotEmpty(posts)) {
            // 新增用户与岗位管理
            List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
            for (Long postId : posts) {
                SysUserPost up = new SysUserPost();
                up.setUserId(user.getUserId());
                up.setPostId(postId);
                list.add(up);
            }
            userPostMapper.batchUserPost(list);
        }
    }

    public void insertUserRole(Long userId, Long[] roleIds) {
        if (ArrayUtil.isNotEmpty(roleIds)) {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
            for (Long roleId : roleIds) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(userId);
                ur.setRoleId(roleId);
                list.add(ur);
            }
            userRoleMapper.batchUserRole(list);
        }
    }

    @Tran
    public int updateUser(SysUser user) {
        Long userId = user.getUserId();
        // 删除用户与角色关联
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 新增用户与角色管理
        insertUserRole(user.getUserId(), user.getRoleIds());
        // 删除用户与岗位关联
        userPostMapper.deleteUserPostByUserId(userId);
        // 新增用户与岗位管理
        insertUserPost(user);
        return sysUserMapper.updateUser(user);
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    public int deleteUserByIds(Long[] userIds) {
        // 删除用户与角色关联
        userRoleMapper.deleteUserRole(userIds);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPost(userIds);
        return sysUserMapper.deleteUserByIds(userIds);
    }

    /**
     * 重置用户密码
     *
     * @param user 用户信息
     * @return 结果
     */
    public int resetPwd(SysUser user) {
        return sysUserMapper.resetUserPwd(user.getUserName(), user.getPassword());
    }

    /**
     * 通过部门id查询当前部门所有用户
     *
     * @param deptId
     * @return
     */
    public List<SysUser> selectUserListByDept(Long deptId) {
        QueryWrapper queryWrapper = QueryWrapper.create();
        queryWrapper.select(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.NICK_NAME, SYS_USER.USER_NAME, SYS_USER.EMAIL, SYS_USER.AVATAR, SYS_USER.PHONENUMBER, SYS_USER.SEX, SYS_USER.STATUS, SYS_USER.DEL_FLAG, SYS_USER.LOGIN_IP, SYS_USER.LOGIN_DATE, SYS_USER.CREATE_BY, SYS_USER.CREATE_TIME, SYS_USER.REMARK)
                .from(SYS_USER).as("u")
                .eq(SysUser::getDeptId, deptId)
                .orderBy(SysUser::getUserId);
        return sysUserMapper.selectListByQuery(queryWrapper);
    }

    public TableDataInfo<SysUser> selectAllocatedPage(SysUser user) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(QueryMethods.distinct(SYS_USER.USER_ID, SYS_USER.TENANT_ID, SYS_USER.DEPT_ID, SYS_USER.USER_NAME, SYS_USER.NICK_NAME, SYS_USER.EMAIL, SYS_USER.PHONENUMBER, SYS_USER.STATUS, SYS_USER.CREATE_TIME))
                .from(SYS_USER.as("u"))
                .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
                .leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
                .leftJoin(SYS_ROLE).as("r").on(SYS_ROLE.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
                .where(SYS_USER.DEL_FLAG.eq(0))
                .and(SYS_ROLE.ROLE_ID.eq(user.getRoleId()));
        if (StringUtils.isNotEmpty(user.getUserName())) {
            queryWrapper.and(SYS_USER.USER_NAME.like(user.getUserName()));
        }
        if (StringUtils.isNotEmpty(user.getPhonenumber())) {
            queryWrapper.and(SYS_USER.PHONENUMBER.like(user.getPhonenumber()));
        }

        Page<SysUser> page = this.pageAs(PageQuery.build(), queryWrapper, SysUser.class);
        return TableDataInfo.build(page);
    }
}
